﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using Newtonsoft.Json.Serialization;
using Sustainalytics.Entities.ESGRatings;
using Sustainalytics.ESGRatings.DataContract.ESG;



using Xunit;
using Xunit.Abstractions;

namespace Sustainalytics.ESGComputing.Service.Tests
{
    public class ESGClientComputingOptionsTest : Disposable, IClassFixture<ComputingFixture>
    {
        private static readonly string _sutLink = "http://localhost:10280/esgcomputingserv/api/v1/esgcompute";

        private static readonly JsonMediaTypeFormatter JsonMediaTypeFormatter = new JsonMediaTypeFormatter
        {
            SerializerSettings = { ContractResolver = new CamelCasePropertyNamesContractResolver() }
        };

        private readonly ComputingFixture _dataFixture;
        private readonly ITestOutputHelper _output;
        private readonly HttpClient _sutClient;
        private bool _disposed;

        public ESGClientComputingOptionsTest(ComputingFixture fixture, ITestOutputHelper output)
        {
            _dataFixture = fixture;
            _output = output;
            _sutClient = new HttpClient();
            _sutClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        }

        ~ESGClientComputingOptionsTest()
        {
            Dispose(false);
        }

        [Fact]
        public void ESGComputeController_Post_Should_Return_Data_For_One_Company_In_Options()
        {
            //Arrange

            var options = new ESGRatingsOptionsDto()
            {
                RefUnivId = _dataFixture.UniverseId,
                MatrixId = _dataFixture.MatrixId,
                CompaniesIds = new List<Guid> { _dataFixture.Companies[0].Id },
                IncludeAggregatedScores = true,
                IncludeIndWeightedScores = true,
                IncludeRatings = true,
                GroupBy = ComparativeGroupEnum.PeerGroup,
            };

            //Act
            var result = _sutClient.PostAsync(_sutLink, options, JsonMediaTypeFormatter);

            var esgRatingsDto = result.Result.Content.ReadAsAsync<ESGRatingsDto>(JsonMediaTypeFormatter.Yield());
            _output.WriteLine(esgRatingsDto.Result.ToString());

            //Assert
            var expected = 1;
            Assert.Equal(expected, esgRatingsDto.Result.Ratings.Count);
        }


        [Fact]
        public void ESGComputeController_Post_Should_Return_Data_For_TopPerformers_In_Options()
        {
            //Arrange

            var options = new ESGRatingsOptionsDto()
            {
                RefUnivId = _dataFixture.UniverseId,
                MatrixId = _dataFixture.MatrixId,
                CompaniesIds = new List<Guid> { _dataFixture.Companies[0].Id },
                IncludeAggregatedScores = true,
                IncludeAggregatedWeights = true,
                IncludeIndWeightedScores = true,
                IncludeRatings = true,
                IncludeTopPerformersInfo = true,
                GroupBy = ComparativeGroupEnum.PeerGroup,
            };

            //Act
            var result = _sutClient.PostAsync(_sutLink, options, JsonMediaTypeFormatter);

            var esgRatingsDto = result.Result.Content.ReadAsAsync<ESGRatingsDto>(JsonMediaTypeFormatter.Yield());
            _output.WriteLine(esgRatingsDto.Result.ToString());

            //Assert
            var expected = 1;
            Assert.Equal(expected, esgRatingsDto.Result.Ratings.Count);
        }


        [Fact]
        public void ESGComputeController_Post_Should_Return_Data_For_Companies_In_Same_Group_As_Company_In_Options()
        {
            //Arrange

            var options = new ESGRatingsOptionsDto()
            {
                RefUnivId = _dataFixture.UniverseId,
                MatrixId = _dataFixture.MatrixId,
                CompaniesIds = new List<Guid> { _dataFixture.Companies[0].Id },
                IncludeAggregatedScores = true,
                IncludeAggregatedWeights = true,
                IncludeIndWeightedScores = true,
                IncludeRatings = true,
                IncludeTopPerformersInfo = true,
                GroupBy = ComparativeGroupEnum.PeerGroup,
                IncludeCompaniesInGroup = true,
            };

            //Act
            var result = _sutClient.PostAsync(_sutLink, options, JsonMediaTypeFormatter);

            var esgRatingsDto = result.Result.Content.ReadAsAsync<ESGRatingsDto>(JsonMediaTypeFormatter.Yield());
            _output.WriteLine(esgRatingsDto.Result.ToString());

            //Assert
            var expected = _dataFixture.Companies.GroupBy(x=>x.PeerGroup).FirstOrDefault(x=>x.Key==_dataFixture.Companies[0].PeerGroup).Select(x=>x.Id).OrderBy(x=>x).ToList();
            var actual = esgRatingsDto.Result.Ratings.Select(x => x.CompanyId).OrderBy(x=>x).ToList();
            Assert.Equal(expected,actual);
        }


        

        protected override void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _sutClient.Dispose();

                }

                _disposed = true;
            }

            base.Dispose(disposing);
        }
    }
}